<?php
/**
 * 好友管理
 * 
 * @author jiaowei<jiaowei@178.com>
 * @version $Id: data.php 12573 2010-12-12 11:21:46Z wangbinxiang $
 */
class friends_model_data extends attention_model_data
{
	/**
	 * 最大好友数
	 *
	 * @var unknown_type
	 */
	private static $_maxFriendCount = 500;
	
	public function __construct()
	{
		parent::__construct();
	}
	
	/**
	 * 添加好友请求
	 *
	 * @param int $hid	登陆用户ID
	 * @param int $uid	要添加的好友ID
	 * @return array
	 */
	public function addFriend($hid, $uid, $msg)
	{	
		$username = $this->checkFriend($hid, $uid);
		
		if ($this->isRequest($uid, $hid)) {//对方已发送过好友请求
			$type = 'bind';
			$this->_addFriend($hid, $uid);
			MemRow::removeCache('friends_cancellist_' . $uid);//我发起的请求列表
		} else {
			$type = 'add';
			if (!$this->addRequest($hid, $uid, $msg)) {
				throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
			}
			MemRow::removeCache('friends_cancellist_' . $hid);//我发起的请求列表
			
			
			/*$roleUtil = Model::factory('armory_util_role');
			$roleUtil->removeRoleFriendCache($hid);*/
			//armory推荐好友
//			MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getGuildFriend', array($hid))));
//			MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getRealmFriend', array($hid))));
		}
		
		return array('type' => $type, 'username' => $username);
	}
	
	/**
	 * 绑定好友
	 *
	 * @param int $hid
	 * @param int $uid
	 * @param bool $noRequest	true:不执行删除好友请求的动作 主要针对邀请好友中直接添加好友的情况
	 * @return str
	 */
	public function bindFriend($hid, $uid, $noRequest = false)
	{
		$username = $this->checkFriend($hid, $uid);
		if (!$noRequest && !$this->isRequest($uid, $hid)) 
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
			
		$this->_addFriend($hid, $uid, $noRequest);
		
		MemRow::removeCache('friends_cancellist_' . $uid);//被确认用户发起的请求列表
		return $username;
	}
	
	/**
	 * 添加好友
	 *
	 * @param int $hid
	 * @param int $uid
	 * @param bool $noRequest
	 */
	private function _addFriend($hid, $uid, $noRequest = false)
	{		
		//$this->db->query("BEGIN");//开始事务
		
		if ($noRequest) {
			if (!$this->add($hid, $uid))
				throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
		} else {
			if (!$this->add($hid, $uid) || !$this->removeRequest($uid, $hid))
				throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
		}
		
		/*
		if ($flag) {
			$this->db->query("COMMIT");
		} else {
			$this->db->query("ROLLBACK");
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
		}
		*/
		
		//添加好友id列表缓存
		MemRow::incrList($uid, array($this, 'getListId', array($hid)));
		MemRow::incrList($hid, array($this, 'getListId', array($uid)));
	}
	
	
	/**
	 * 删除好友
	 *
	 * @param int $hid
	 * @param int $uid
	 */
	public function removeFriend($hid, $uid)
	{
		$username = $this->checkFriend($hid, $uid, true);
		
		if (!$this->remove($hid, $uid))
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
		
		//好友所属的所有分组
		$groups = Model::factory('friends_model_group')->getFriendGroup($hid, $uid);
		if ($groups) {				
			$groupIds = array();
			foreach ($groups as $v) {
				$groupIds[] = $v['group_id'];
				
				//删除该分类中的好友id
				MemRow::decrList($uid, array(Model::factory('friends_model_group'), 'getListId', array($hid, $v['group_id'])));
				
				//修改该分组的好友人数-1
				if ($groupInfo = MemRow::mget('friends_group', $v['group_id'], array(Model::factory('friends_model_group'), 'getGroupRow'))) {
					if ($groupInfo['group_nums'] > 0) $groupInfo['group_nums'] -= 1;
					MemRow::mset(MemRow::genRowKey('friends_group', $v['group_id']), $groupInfo);
				}
			}
			
			//修改分组好友人数 -1
			Model::factory('friends_model_group')->editGroupFriendsNums($groupIds);
		}
		
		//删除该好友所有所属分组的从属关系
		Model::factory('friends_model_group')->delFriendFromGroup($hid, $uid);
		
		//好友id列表缓存
		MemRow::decrList($uid, array($this, 'getListId', array($hid)));
		MemRow::decrList($hid, array($this, 'getListId', array($uid)));
	}
	
	/**
	 * 拒绝好友邀请
	 *
	 * @param int $hid
	 * @param int $uid
	 * @return str
	 */
	public function refuseRequest($hid, $uid)
	{
		$username = $this->checkFriend($hid, $uid, true);
		
		if (!$this->removeRequest($uid, $hid))
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
			
		MemRow::removeCache('friends_cancellist_' . $uid);//我发起的请求列表
		
		/*$roleUtil = Model::factory('armory_util_role');
		$roleUtil->removeRoleFriendCache($hid);*/
		//armory推荐好友
//		MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getGuildFriend', array($hid))));
//		MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getRealmFriend', array($hid))));
		return $username;
	}
	
	/**
	 * 取消好友请求
	 *
	 * @param int $hid
	 * @param int $uid
	 * @return str
	 */
	public function cancelRequest($hid, $uid)
	{
		$username = $this->checkFriend($hid, $uid, true);
		
		if (!$this->removeRequest($hid, $uid))
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UNKNOWN);
		
		MemRow::removeCache('friends_cancellist_' . $hid);//我发起的请求列表
		
		/*$roleUtil = Model::factory('armory_util_role');
		$roleUtil->removeRoleFriendCache($hid);*/
		//armory推荐好友
//		MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getGuildFriend', array($hid))));
//		MemRow::removeCache(MemRow::genListKey(array('armory_model_data', 'getRealmFriend', array($hid))));
		return $username;
	}
	
	/**
	 * 好友验证
	 *
	 * @param int $hid
	 * @param int $uid
	 * @param bool $break
	 * @return str
	 */
	public function checkFriend($hid, $uid, $break = false)
	{			
		$uid = (int) $uid;
		$userInfo = friends_util_cache::getUserInfo($uid);
			
		if (!$userInfo['username'])
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_NO_USER);
		
		if ($uid == $hid)
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_SELF);
			
		if ($break) return $userInfo['username'];
		
		if ($this->isFriend($hid, $uid))
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_EXISTS);
			
		/*if (index_util_baduser::isBad($uid, $hid))
			throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_SECRET);*/
			
		//是否为好友的好友
		/*$privacy = index_util_prop::getDefaultSrank($uid, 'friends');
		if ($privacy == index_util_prop::FRIEND_ONLYFRIEND )
			if (!friends_util_checker::isFriendOfMyFriend($uid, $hid))
				throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_ONLYFRIEND);*/
				
		//好友人数上限检测
		/*if (is_array($_SERVER['friends']['allow']) && (!in_array($uid, $_SERVER['friends']['allow']) && 
			!in_array($hid, $_SERVER['friends']['allow']))) {//被加的人是否检测好友上线
			$friendCount = friends_util_friendutil::getFriendIds($uid);
			$myCount   	 = friends_util_friendutil::getFriendIds($hid);
			if ( (count($friendCount) >= self::$_maxFriendCount) || (count($myCount) >= self::$_maxFriendCount))
				throw new friends_util_exception(friends_util_exception::API_EC_FRIEND_UPPER);
		}*/
		
		return $userInfo['username'];
	}
	
	/**
	 * 获取等待确认的请求列表
	 *
	 * @param int $hid
	 * @return array
	 */
	public function getRequests($uid)
	{
		$uid = (int) $uid;
		if (!$uid) return false;
		$listId = $this->db->fetchAll("SELECT `host_id`,`msg`,`create_time` FROM {$this->request_table} WHERE uid=&uid", array('uid' => $uid));
		
		$requests = array();
		$msgs	  = array();
		foreach ($listId as $v) {
			$requests[] = $v['host_id'];
			$msgs[$v['host_id']] = $v['msg'];
		}
		
		$userInfo = friends_util_cache::getUserInfo($requests);
		
		$result = array();
		foreach ($userInfo as $k => $v) 
			$result[] = array('uid' => $v['id'], 'username' => $v['username'], 'msg' => $msgs[$v['id']]);
		
		return $result;
	}
	
	/**
	 * 获取已经发送的好友请求
	 *
	 * @param int $hid
	 * @return array
	 */
	public function getCancels($uid)
	{
		$uid = (int) $uid;
		if (!$uid) return array();
		
		$key = 'friends_cancellist_' . $uid;
		$result = MemRow::getCache($key);

		if ((false === $result) || (null === $result)) {
			$listId = $this->db->fetchAll("SELECT `uid` FROM {$this->request_table} WHERE host_id=&uid", array('uid' => $uid));
			$result = array();
			foreach ($listId as $v) {
				$result[] = $v['uid'];
			}
			MemRow::mset($key, $result);
		}
		
		return $result;
	}
	
	/**
	 * 添加好友
	 *
	 * @param int $aid
	 * @param int $bid
	 * @return bool
	 */
	public function add($hid, $uid)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$sql  = "INSERT IGNORE INTO {$this->table} (`uid`, `host_id`, `create_time`) VALUES ";
		$sql .= "('{$uid}', '{$hid}', '{$_SERVER['REQUEST_TIME']}'), ('{$hid}', '{$uid}', '{$_SERVER['REQUEST_TIME']}')";
		return $this->db->query($sql);
	}
	
	/**
	 * 添加请求
	 *
	 * @param int $hid
	 * @param int $uid
	 * @param str $msg
	 * @return bool
	 */
	public function addRequest($hid, $uid, $msg)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		$msg = addslashes(trim($msg));
		
		$sql = "INSERT IGNORE INTO {$this->request_table} (`uid`, `host_id`, `msg`, `create_time`) VALUES ('{$uid}', '{$hid}', '{$msg}', '{$_SERVER['REQUEST_TIME']}')";
		return $this->db->query($sql);
	}
	
	/**
	 * 删除好友
	 *
	 * @param int $hid
	 * @param int $uid
	 * @return bool
	 */
	public function remove($hid, $uid)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$sql = "DELETE FROM {$this->table} WHERE (host_id=&host_id AND uid=&uid) OR (host_id=&uid AND uid=&host_id)";
		$params = array('host_id' => $hid, 'uid' => $uid,);
		return $this->db->query($sql, $params);
	}
	
	/**
	 * 删除好友请求
	 *
	 * @param int $hid
	 * @param int $uid
	 * @return bool
	 */
	public function removeRequest($hid, $uid)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$sql = "DELETE FROM {$this->request_table} WHERE host_id=&host_id AND uid=&uid LIMIT 1";
		$params = array('host_id' => $hid, 'uid' => $uid);
		return $this->db->query($sql, $params);
	}
	
	/**
	 * 是否是好友
	 *
	 * @param int $hid
	 * @param int $uid
	 * @return bool
	 */
	public function isFriend($hid, $uid)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$sql = "SELECT `uid` FROM {$this->table} WHERE host_id = &host_id AND uid = &uid";
		$params = array('host_id' => $hid, 'uid' => $uid);

		return $this->db->fetchField($sql, 'uid', $params);
		
		//$friendId = friends_util_cache::getFriendIds($hid);
		//return in_array($uid, $friendId);
	}
	
	/**
	 * 是否发送过请求
	 *
	 * @param int $host_id
	 * @param int $uid
	 * @return bool
	 */
	public function isRequest($hid, $uid)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$sql = "SELECT `uid` FROM {$this->request_table} WHERE host_id = &host_id AND uid = &uid";
		$params = array('host_id' => $hid, 'uid' => $uid);

		return $this->db->fetchField($sql, 'uid', $params);
	}
	
	/**
	 * 两个用户共同的好友
	 *
	 * @param int $uid1
	 * @param int $uid2
	 * @return array
	 */
	public function commFriends($uid1, $uid2)
	 {
		$friend1 = friends_util_cache::getFriendIds($uid1);
		$friend2 = friends_util_cache::getFriendIds($uid2);
	 	
		$friendId = array_intersect($friend1, $friend2);
		
		$result = friends_util_cache::getUserInfo($friendId);

		foreach ($result as $k => $v)//兼容之前的方法 冗余uid字段
			$result[$k]['uid'] = $v['id'];
		
		return $result;
	}

	/**
	 * 分页获取用户列表  （后台用）
	 *
	 * @param int $uid
	 * @param int $friend
	 * @param int $page
	 * @param int $pageSize
	 * @return array
	 */
	public function selectByPage($uid, $friend, $page, $pageSize)
	{
		$sql = "SELECT * FROM {$this->table} WHERE host_id=&uid";
		$params = array('uid' => $uid);
		return $this->db->selectPage($sql, $params, $page, $pageSize);
	}
	
	/**
	 * 获取好友列表
	 *
	 * @param int $uid
	 * @param int $limit
	 * @return array
	 */
	public function getFriendList($uid, $limit = 9)
	{
		$friendId = friends_util_cache::getFriendIds($uid, $limit);
		$result   = friends_util_cache::getUserInfo($friendId);
		
		foreach ($result as $k => $v)//兼容之前的方法 冗余uid字段
			$result[$k]['uid'] = $v['id'];
		
		return $result;
	}
	
	/**
	 * 是否是我要好的好友
	 *
	 * @param int $host_id
	 * @param int $uid
	 * @return int
	 */
	public function isFriendOfMyFriend($host_id, $uid)
	{
		$friendId = friends_util_cache::getFriendIds($host_id);
		if (!$friendId) return false;
		
		$friendId = implode(',', $friendId);
		$sql = "SELECT `uid` FROM {$this->table} WHERE host_id IN ($friendId) AND uid = &uid";
		$params = array('uid' => $uid);
		return $this->db->fetchField($sql, 'uid', $params);
	}
	
	/**
	 * 加好友任务接口
	 *
	 * @param int $uid
	 * @param int $time
	 * @return int
	 */
	public function questCheck($uid, $time)
	{
		$sql = "select count(*) c from {$this->table} where (host_id=&uid) and create_time > &time";
		$params = array('uid' => $uid, 'time' => $time);
		return $this->db->fetchField($sql, 'c', $params);
	}
	
	/**
	 * 获取好友最多的用户
	 *
	 * @return array
	 */
	public function getTopFriendsOwner()
	{
		$sql  = "SELECT count(*) c, host_id FROM {$this->table} GROUP BY host_id ORDER BY c DESC limit 20";
		$stat = $this->db->fetchAll($sql);
		
		$user = array();
		$top  = array();
		foreach ($stat as $k => $v) {
			$user[] = $v['host_id'];
			$top[$v['host_id']] = $v['c'];
		}
		
		$userInfo = friends_util_cache::getUserInfo($user);
		
		$result = array();
		foreach ($userInfo as $k => $v) 
			$result[] = array('uid' => $v['id'], 'username' => $v['username'], 'c' => $top[$v['id']]);
		
		return $result;
	}
	
	/**
	 * 获取平均好友数
	 *
	 * @return int
	 */
	public function getAvgFriends()
	{
		$sql = "SELECT AVG(c) a FROM (SELECT count(*) c FROM {$this->table} GROUP BY host_id) t";
		return $this->db->fetchField($sql, 'a');
	}
	
	/**
	 * 获取随机好友
	 *
	 * @param int $uid
	 * @param int $num
	 * @return array
	 */
	public function getRandomFriends($uid, $num)
	{
		$friendId = friends_util_cache::getFriendIds($uid);
		if (!$friendId) return null;
		
		shuffle($friendId);
		
		if (count($friendId) > $num) $friendId = array_splice($friendId, 0, $num);
		
		$result = friends_util_cache::getUserInfo($friendId);
		
		foreach ($result as $k => $v)//兼容之前的方法 冗余uid字段
			$result[$k]['uid'] = $v['id'];
		
		return $result;
	}
	
	
	/**
	 * 修改好友备注
	 *
	 * @param int $hid
	 * @param int $uid
	 * @param str $remark
	 * @return bool
	 */
	public function editRemark($hid, $uid, $remark)
	{
		$hid = (int) $hid;
		$uid = (int) $uid;
		if (!$hid || !$uid) return false;
		
		$newRemark = addslashes(trim($remark));
		
		$sql = "INSERT INTO {$this->remark_table} (`uid`, `host_id`, `remark`) VALUES ('{$uid}', '{$hid}', '{$newRemark}') ON DUPLICATE KEY UPDATE remark='{$newRemark}'";
		$this->db->query($sql);
		
		if (false !== ($remarks = $this->getRemark($hid))) {
			$remarks[$uid] = $remark;
			MemRow::mset(self::_genRemarkKey($hid), $remarks);
		}
	}
	
	/**
	 * 好有备注cache key
	 *
	 * @param int $uid
	 * @return str
	 */
	private static function _genRemarkKey($uid)
	{
		return 'friends_remarks_' . $uid;
	}
	
	/**
	 * 返回好友备注
	 *
	 * @param int $hid
	 * @return array
	 */
	public function getRemark($hid)
	{
		$hid = (int) $hid;
		if (!$hid) return false;
		
		$key = self::_genRemarkKey($hid);
		$result = MemRow::getCache($key);
		
		if ((false === $result) || (null === $result)) {
			$remarks = $this->db->fetchAll("SELECT remark,uid FROM {$this->remark_table} WHERE host_id =&hostId", array('hostId' => $hid));
			
			$result = array();
			foreach ((array) $remarks as $v) {
				if($v['remark'])
					$result[$v['uid']] = $v['remark'];
			}
			MemRow::mset($key, $result);
		}
		
		return $result;
	}

	
	/**
	 * 获取用户详细信息
	 *
	 * @param array $uids
	 * @return array
	 */
	public function getRow($uids)
	{
		$uids = implode(',', (array) $uids);
		
		return $this->db->fetchAll("SELECT * FROM cartoon_members WHERE uid IN({$uids})");
	}
	
	/**
	 * 获取好友ID列表
	 *
	 * @param int $hid	该参数必须是一个整数
	 * @return array
	 */
	public function getListId($hid)
	{
		$listId = $this->db->fetchAll("SELECT uid FROM {$this->table} WHERE host_id=&hostId ORDER BY id DESC", array('hostId' => $hid));
		
		$result = array();
		foreach ($listId as $v) {
			$result[] = $v['uid'];
		}
		return $result;
	}
	
	
	/**
	 * 获取多个用户的好友id列表
	 * 
	 * 此方法供好友动态数据Java分发使用
	 *
	 * @param str $uids   2383104,10022
	 * @return str
	 */
	public function getFriendId($uids)
	{
		$tem = $this->db->fetchAll("SELECT `uid`,`host_id` FROM {$this->table} WHERE `host_id` IN ({$uids})");

		if (!$tem) return 'null';
		
		$friend = array();
		foreach ((array) $tem as $v) {
			$friend[$v['host_id']][] = $v['uid'];
		}

		$result = '';
		foreach ((array) $friend as $key => $val) {
			$result .= $key . '|' . implode(',', $val) . "\n"; 
		}
		$result = trim($result, "\n");
		return $result;
	}	
}
